package org.noote.spidy.monitor;

import javax.microedition.khronos.opengles.GL10;

import org.noote.libs.robot.Robot_Animation;
import org.noote.libs.robot.object3d.Robot_Skeleton3D;
import org.noote.libs.sogle.Light;
import org.noote.libs.sogle.Quaternion;
import org.noote.libs.sogle.Vector3D;
import org.noote.libs.sogle.helper.LineMesh_Grid;
import org.noote.libs.spidy.anim.Spidy_WildRobot;
import org.noote.libs.widget.WidgetEvent_OnChangeItem;
import org.noote.libs.widget.WidgetEvent_OnClick;
import org.noote.libs.widget.WidgetEvent_OnTouch;
import org.noote.libs.widget.WidgetRenderer;
import org.noote.libs.widget.WidgetTexturePack;
import org.noote.libs.widget.Widget_Carousel;
import org.noote.libs.widget.Widget_CarouselItem;
import org.noote.libs.widget.Widget_DirectionPad;
import org.noote.libs.widget.Widget_Label;
import org.noote.libs.widget.Widget_Pad;
import org.noote.libs.widget.Widget_Window;
import org.noote.libs.widget.Widget_ZoomPad;

import android.content.Context;
import android.opengl.GLSurfaceView;
import android.view.MotionEvent;

class Spidy_GLView extends GLSurfaceView {
	
    public Widget_DirectionPad _view_dir_pad;
    public Widget_ZoomPad _view_zoom_pad;
    public Widget_Carousel _animation_carousel;
    public Widget_Label _label_message, _label_range, _label_guiFPS;
    public Widget_Pad _draw_mode_pad;
    public Widget_DirectionPad _spidy_dir_pad;

	private SpidyRenderer _renderer;
	private Spidy_Activity _activitySpidy;
	
    float _fUpCameraFactor = 0.5f, _fUpCameraLootAtMin=3, _fUpCameraLookAtMax=40, _fUpCameraMin=1, _fUpCameraMax=45;
    float _fRotCamera = 0;
    float _fZoomCameraFactor = 0.75f, _fZoomCameraMin=20, _fZoomCameraMax=60;
    
    int _iDrawMode=2;

	class SpidyRenderer extends WidgetRenderer
	{
		/**
		 * 
		 */
		static final int TEX_SHOW_WIRED=0, TEX_SHOW_BOXES=1, TEX_SHOW_MESHES=2;
		WidgetTexturePack _myTextures = new WidgetTexturePack();
		WidgetTexturePack _myAnimationIcons = new WidgetTexturePack();
		Light _light=null;
		
	    public SpidyRenderer(Context context)
	    {
	    	super(context);
	    }
	    
	    @Override
	    public void onCreateScene(GL10 gl)
		{
			super.onCreateScene(gl);
			
			if(_myTextures.create(gl, 3))
			{
	    		_myTextures.loadImageFromResource(_context, R.drawable.robot_wired, gl, TEX_SHOW_WIRED);
	    		_myTextures.loadImageFromResource(_context, R.drawable.robot_boxes, gl, TEX_SHOW_BOXES);
	    		_myTextures.loadImageFromResource(_context, R.drawable.robot_wired, gl, TEX_SHOW_MESHES);
			}
			
	        lighting(false);
	        
	        setBackGroundColor(0.5f, 0.5f, 0.5f);

	        _camera.setLookAt(new Vector3D(0, 20, 50), new Vector3D(0, 20, 0), 0);
	        
	        LineMesh_Grid floor = new LineMesh_Grid(50.0f, 50.0f, 20, 20);
	        //Mesh_Plane floor = new Mesh_Plane(50.0f, 50.0f, 10, 10);
	        _listObjects.add(floor);
	        
	        _activitySpidy._bot = new Spidy_WildRobot();
	        _activitySpidy._bot.create();
	        _activitySpidy._bot3d = new Spidy_Skeleton3D(_activitySpidy._bot);
	        _activitySpidy._bot3d.create(_activitySpidy.getBaseContext());
	        _activitySpidy._bot3d.setPosition(0,10,0);
	        _listObjects.add(_activitySpidy._bot3d);
	        
	        _light = new Light();
	        _light.enable(true);
	        _listLights.add(_light);
	        
	        _label_message = _dekstop.createLabel();
	        _label_message.setWorkSpace(getWidth()/2, 32, 256, 32);
	        _label_message.setTextColor(0, 1, 1);
	        _dekstop.add(_label_message);
	        
	        _label_range = _dekstop.createLabel();
	        _label_range.setWorkSpace(getWidth()/2, getHeight()/2, 256, 32);
	        _label_range.setTextColor(0.5f, 0.1f, 0.1f);
	        _dekstop.add(_label_range);            
	        
	        // a carroussel with all animation loops
	        int iAnimCount=0;
	        _myAnimationIcons.create(gl, _activitySpidy._bot._anims.size());
	        _animation_carousel = _dekstop.createCarousel();
	        _animation_carousel.setRightDocked();
	        for(Robot_Animation a : _activitySpidy._bot._anims)
	        {
	        	// TODO
	        	_myAnimationIcons.loadImageFromResource(_context, R.drawable.no_anim, gl, iAnimCount);
	        	
	        	Widget_CarouselItem item = _animation_carousel.createCarouselItem();
	        	item.setText(a.getName());
	        	item.setLongData(iAnimCount);
	        	item.setIcon(_myAnimationIcons.getTextureID(iAnimCount));
	        	_animation_carousel.add(item);
	        	
	        	iAnimCount++;
	        }
	        _animation_carousel.setOnChangeItem(new WidgetEvent_OnChangeItem()
	        {
				@Override
				public boolean onSelectedItem(Widget_Window window, Widget_Window item) {
	    			_activitySpidy._iAnimationChoosen = (int)item.getLongData();
	    			if(_activitySpidy._iAnimationChoosen>0)
	    			{
	    				_spidy_dir_pad.enableWindow(true);
	    			}
	    			else
	    			{
	    				_spidy_dir_pad.enableWindow(false);
	    			}
					return true;
				}
	        });
	        _animation_carousel.selectItem(0);
	        _animation_carousel.enableWindow(false);
	        _dekstop.add(_animation_carousel);

	        // directional pad :)
	        _view_dir_pad = _dekstop.createDirectionPad();
	        _view_dir_pad.setPosition(_view_dir_pad.getWidth()/2, getHeight()-(int)(_view_dir_pad.getHeight()*2.5f));
	        _view_dir_pad.setOnTouch(new WidgetEvent_OnTouch()
	        {
				@Override
				public boolean onPressed(Widget_Window window) {

					if(_view_dir_pad.getButtonUp())
		    		{
		    			_activitySpidy._move_up = true;
		    			_activitySpidy._move_down = false;
		    		}
		    		else if(_view_dir_pad.getButtonDown())
		    		{
		    			_activitySpidy._move_up = false;
		    			_activitySpidy._move_down = true;
		    		}
		    		if(_view_dir_pad.getButtonRight())
		    		{
		    			_activitySpidy._rotate_right = true;
		    			_activitySpidy._rotate_left = false;
		    		}
		    		else if(_view_dir_pad.getButtonLeft())
		    		{
		    			_activitySpidy._rotate_right = false;
		    			_activitySpidy._rotate_left = true;
		    		}
		    		
					return true;
				}

				@Override
				public boolean onMoved(Widget_Window window) {
					return true;
				}

				@Override
				public boolean onReleased(Widget_Window window) {
					_activitySpidy._move_up = _activitySpidy._move_down = _activitySpidy._rotate_right = _activitySpidy._rotate_left = false;
					return true;
				}
	        });
	        _dekstop.add(_view_dir_pad); 	

	        // zoom pad :)
	        _view_zoom_pad = _dekstop.createZoomPad();
	        _view_zoom_pad.setPosition(_view_zoom_pad.getWidth()/2, (int)(_view_zoom_pad.getHeight()*1.5f));
	        _view_zoom_pad.setOnTouch(new WidgetEvent_OnTouch()
	        {
				@Override
				public boolean onPressed(Widget_Window window) {

	    			if(_view_zoom_pad.getButtonFront())
	    			{
	    				_activitySpidy._move_front = true;
	    				_activitySpidy._move_back = false;
	    			}
	    			else if(_view_zoom_pad.getButtonBack())
	    			{
	    				_activitySpidy._move_front = false;
	    				_activitySpidy._move_back = true;	    	    				
	    			}
		    		
					return true;
				}

				@Override
				public boolean onMoved(Widget_Window window) {
					return true;
				}

				@Override
				public boolean onReleased(Widget_Window window) {
					_activitySpidy._move_front = _activitySpidy._move_back = false;
					return true;
				}
	        });
	        _dekstop.add(_view_zoom_pad);

	        // draw options
	        _draw_mode_pad = _dekstop.createPad();
	        _draw_mode_pad.setPosition(0, 0);
	        _draw_mode_pad.setText("Wired");
	        _draw_mode_pad.setIcon(_myTextures.getTextureID(TEX_SHOW_WIRED));
	        _draw_mode_pad.setOnClick(new WidgetEvent_OnClick()
	        {
				@Override
				public boolean onClick(Widget_Window window) {
	    			setDrawMode(_iDrawMode+1);
					return true;
				}
	        });
	        _dekstop.add(_draw_mode_pad);
	        
	        _label_guiFPS = _dekstop.createLabel();
	        _label_guiFPS.setTextColor(_dekstop.getTheme().colorLightGray);
	        _label_guiFPS.setWorkSpace(_draw_mode_pad.getPositionX()+16, _draw_mode_pad.getPositionY()+_draw_mode_pad.getHeight()+16, 128, 32);
	        _dekstop.add(_label_guiFPS);

	        // directional pad :)
	        _spidy_dir_pad = _dekstop.createDirectionPad();
	        _spidy_dir_pad.setSize((int)(_spidy_dir_pad.getWidth()*1.5f), (int)(_spidy_dir_pad.getHeight()*1.5f));
	        _spidy_dir_pad.setPosition((int)(getWidth()-_animation_carousel.getWidth()-_spidy_dir_pad.getWidth()*1.25f), getHeight()/2-_spidy_dir_pad.getHeight()/2);
	        _spidy_dir_pad.setOnTouch(new WidgetEvent_OnTouch()
	        {
				@Override
				public boolean onPressed(Widget_Window window) {

					if(_spidy_dir_pad.getButtonUp())
		    		{
						_activitySpidy._bot.goFront(1);
		    		}
		    		else if(_spidy_dir_pad.getButtonDown())
		    		{
		    			_activitySpidy._bot.goBack(1);
		    		}
		    		if(_spidy_dir_pad.getButtonRight())
		    		{
		    			_activitySpidy._bot.turnRight(1);
		    		}
		    		else if(_spidy_dir_pad.getButtonLeft())
		    		{
		    			_activitySpidy._bot.turnLeft(1);
		    		}
		    		
					return true;
				}

				@Override
				public boolean onMoved(Widget_Window window) {
					return true;
				}

				@Override
				public boolean onReleased(Widget_Window window) {
					_activitySpidy._bot.setNeutral();
					return true;
				}
	        });
	        _dekstop.add(_spidy_dir_pad); 	

	        calculCameraPosition();
	        
			setDrawMode(2);
		}
		
		@Override
	    public void onFrame(float fTimeSlice) {

	    	// Camera stuff
			if(_activitySpidy._move_front)
				_fZoomCameraFactor -= 0.25*fTimeSlice;
			else if(_activitySpidy._move_back)
				_fZoomCameraFactor += 0.25*fTimeSlice;
			_fZoomCameraFactor = _fZoomCameraFactor>1.0f?1.0f:_fZoomCameraFactor<0?0:_fZoomCameraFactor;
			if(_activitySpidy._move_up)
				_fUpCameraFactor += 0.25*fTimeSlice;
			else if(_activitySpidy._move_down)
				_fUpCameraFactor -= 0.25*fTimeSlice;
			_fUpCameraFactor = _fUpCameraFactor>1.0f?1.0f:_fUpCameraFactor<0?0:_fUpCameraFactor;
			if(_activitySpidy._rotate_left)
				_fRotCamera += 35.0*fTimeSlice;
			else if(_activitySpidy._rotate_right)
				_fRotCamera -= 35.0*fTimeSlice;
			_fRotCamera = _fRotCamera>145.0f?145.0f:_fRotCamera<-145?-145:_fRotCamera;
			
			calculCameraPosition();
			
			_label_guiFPS.setText(String.format("App FPS : %2.1f", _fps.getFPS()));
			_label_range.setText(String.format("Range : %3dcm", _activitySpidy._states._iFrontRange));
	    
			// Robot anim
			if(_activitySpidy._bot.isAnimationFinish())
				_activitySpidy._bot.setAnimation(_activitySpidy._iAnimationChoosen);
			_activitySpidy._bot.doAnimation(fTimeSlice);
	    	_activitySpidy._bot.update();
		}

	    void setDrawMode(int iMode)
	    {
	    	_iDrawMode = iMode%4;
	    	switch(_iDrawMode)
	    	{
	    	case 0:
				_activitySpidy._bot3d.drawMode(Robot_Skeleton3D._DRAW_WIRED);
				lighting(false);
				_draw_mode_pad.setText("Wire");
				_draw_mode_pad.setIcon(_myTextures.getTextureID(TEX_SHOW_WIRED));
	    		break;
	    	case 1:
	    		_activitySpidy._bot3d.drawMode(Robot_Skeleton3D._DRAW_BOX);
				lighting(false);
				_draw_mode_pad.setText("Box");
				_draw_mode_pad.setIcon(_myTextures.getTextureID(TEX_SHOW_BOXES));
	    		break;
	    	case 2:
	    		_activitySpidy._bot3d.drawMode(Robot_Skeleton3D.DRAW_MESH);
				lighting(true);
				_draw_mode_pad.setText("Mesh");
				_draw_mode_pad.setIcon(_myTextures.getTextureID(TEX_SHOW_MESHES));
	    		break;
	    	case 3:
	    		_activitySpidy._bot3d.drawMode(Robot_Skeleton3D._DRAW_WIRED + Robot_Skeleton3D.DRAW_MESH);
				lighting(false);
				_draw_mode_pad.setText("Mesh+Wire");
				_draw_mode_pad.setIcon(_myTextures.getTextureID(TEX_SHOW_MESHES));
	    		break;
	    	}
	    }
	    
	    void calculCameraPosition()
	    {
	    	Vector3D vLookAt=new Vector3D(), vPosition=new Vector3D();
	    	
			Quaternion qCamera = Quaternion.fromEuler(0, _fRotCamera, 0);
			vLookAt.set(0f, _fUpCameraLootAtMin+_fUpCameraLookAtMax*_fUpCameraFactor, 0f);
			vPosition.set(0f, _fUpCameraMin+_fUpCameraMax*_fUpCameraFactor, _fZoomCameraMin+_fZoomCameraMax*_fZoomCameraFactor);
			
			// rotation
			vPosition = Quaternion.mult(qCamera, vPosition);
			
			_camera.setLookAt(vPosition, vLookAt, 0f);
			
			//_light.setPosition(vPosition.x, vPosition.y, vPosition.z);
			_light.setDirection(vPosition.x, vPosition.y+2.0f, vPosition.z);
	    }
	}
    
    public Spidy_GLView(Spidy_Activity activitySpidy, Context context) {
        super(context);
        
		this._activitySpidy = activitySpidy;
		
        _renderer = new SpidyRenderer(context);
        setRenderer(_renderer);
        setPreserveEGLContextOnPause(true);
    }

    @Override
	public boolean onTouchEvent(final MotionEvent event)
    {
        queueEvent(new Runnable(){
            @Override
			public void run() {
            	
    	    	_renderer.onTouchEvent(event);

            }});
        return true;
    }
}